/* Initial beliefs and rules */
last_contract_id(0).
// initially, I believe that there is some beer in the fridge
available(beer,fridge).

// my owner should not consume more than 10 beers a day :-)
limit(beer,24). 

too_much(B) :- 
   .date(YY,MM,DD) &
   .count(consumed(YY,MM,DD,_,_,_,B),QtdB) &
   limit(B,Limit) &
   QtdB > Limit.

all_proposals_received(CNPId) 
  :- .count(introduction(participant,_),NP) & // number of participants
     .count(propose(CNPId,_), NO) &           // number of proposes received
     .count(refuse(CNPId), NR) &              // number of refusals received
     NP = NO + NR.

/* Plans */

// start the CNP
+!startCNP(Id,Task) 
   <- .print("Waiting participants...");
      .wait(2000);  // wait participants introduction
      +cnp_state(Id,propose);   // remember the state of the CNP
      .findall(Name,introduction(participant,Name),LP);
      .print("Sending CFP to ",LP);
      .send(LP,tell,cfp(Id,Task));
      // the deadline of the CNP is now + 4 seconds, so
      // the event +!contract(Id) is generated at that time
      .at("now +4 seconds", { +!contract(Id) }).


// receive proposal 
// if all proposal have been received, don't wait for the deadline
@r1 +propose(CNPId,_Offer)
   :  cnp_state(CNPId,propose) & all_proposals_received(CNPId)
   <- !contract(CNPId).

// receive refusals   
@r2 +refuse(CNPId) 
   :  cnp_state(CNPId,propose) & all_proposals_received(CNPId)
   <- !contract(CNPId).

// this plan needs to be atomic so as not to accept
// proposals or refusals while contracting
@lc1[atomic]
+!contract(CNPId)
   :  cnp_state(CNPId,propose)
   <- -+cnp_state(CNPId,contract);
      .findall(offer(O,A),propose(CNPId,O)[source(A)],L);
      .print("Offers are ",L);
      L \== []; // constraint the plan execution to at least one offer
      .min(L,offer(WOf,WAg)); // sort offers, the first is the best
      .print("Winner is ",WAg," with ",WOf);
      !announce_result(CNPId,L,WAg);
      -+cnp_state(CNPId,finished).

// nothing todo, the current phase is not 'propose'
@lc2 +!contract(_). 

-!contract(CNPId)
   <- .print("CNP ",CNPId," has failed!").

+!announce_result(_,[],_).
// announce to the winner
+!announce_result(CNPId,[offer(_,WAg)|T],WAg) 
   <- .send(WAg,tell,accept_proposal(CNPId));
      !announce_result(CNPId,T,WAg).
	
// announce to others
+!announce_result(CNPId,[offer(_,LAg)|T],WAg) 
   <- .send(LAg,tell,reject_proposal(CNPId));
      !announce_result(CNPId,T,WAg).

//existing stuff

+!has(owner,beer)
   :  available(beer,fridge) & not too_much(beer)
   <- !at(robot,fridge);
      open(fridge);
      get(beer);
      close(fridge);
      !at(robot,owner);
      hand_in(beer);
      ?has(owner,beer);
      // remember that another beer has been consumed
      .date(YY,MM,DD); .time(HH,NN,SS);
      +consumed(YY,MM,DD,HH,NN,SS,beer).

+!has(owner,beer)
   :  not available(beer,fridge)
  /*
   <- .send(supermarket, achieve, order(beer,12));
      !at(robot,fridge). // go to fridge and wait there.
*/
	<-?last_contract_id(N);
     ContractId = N + 1;
     -+last_contract_id(ContractId);//get the next contract id
	 !startCNP(ContractId,order(beer,5));// initiate the negotiation for beer
	 !at(robot,fridge). //go to the fridge and wait there.

+!has(owner,beer)
   :  too_much(beer) & limit(beer,L)    
   <- .concat("The Department of Health does not allow me to give you more than ", L, 
              " beers a day! I am very sorry about that!",M);
      .send(owner,tell,msg(M)).    

   
-!has(_,_)
   :  true
   <- .current_intention(I); 
      .print("Failed to achieve goal '!has(_,_)'. Current intention is: ",I).
   
+!at(robot,P) : at(robot,P) <- true.
+!at(robot,P) : not at(robot,P)
  <- move_towards(P);
     !at(robot,P).

// when the supermarket makes a delivery, try the 'has' goal again   
+delivered(beer,_Qtd,_ContractId)[source(A)] : true 
  <- +available(beer,fridge);
  .print("Beer has been delivered by:",A," as part of contract:",_ContractId);
     !has(owner,beer). 
   
// when the fridge is opened, the beer stock is perceived
// and thus the available belief is updated
+stock(beer,0) 
   :  available(beer,fridge)
   <- -available(beer,fridge).
+stock(beer,N) 
   :  N > 0 & not available(beer,fridge)
   <- -+available(beer,fridge).

 +completed_contract(CNPId)[source(A)]:true
 <- .print(A," has reported that the contract ",CNPId," has been completed.").
 
+?time(T) : true
  <-  ca.athabascau.quizmaster.example.time.check(T).

